package com.mec.fileTransfer.core;

import java.util.LinkedList;
import java.util.List;

/**
 * 这个类中的List集合了资源中未接受部分的块信息
 * 并且提供了通过偏移量得到当前偏移量所在的未接收的文件信息块的方法
 * 提供了方法：通过一个RB对象，解析出其所表示的文件资源块，并且通过
 * 一定算法对“未接收的文件信息块”列表进行更新，保证能及时的描述当前的
 * 资源的接受块信息的散列情况。
 * @param fileLength
 */
public class UnreceivedBlockInfo {
	private List<FileBlockInfo> blockList;

	public UnreceivedBlockInfo() {
	}
	
	public UnreceivedBlockInfo(long fileLength) {
		blockList = new LinkedList<>();
		blockList.add(new FileBlockInfo(0, fileLength));
	}
	
	protected List<FileBlockInfo> getBlockList() {
		return blockList;
	}
	
	//通过当前的偏移量找到这个偏移量所在的块的列表下标（顺序比较查找）
	int getBlockIndex(long curOffset) {
		int result = 0;
		for(; blockList.get(result).getOffset() + blockList.get(result).getLength() < curOffset;
						result++);
		
		return result;
	}
	
	synchronized void receiveBlock(ResourceBlock rb) {
		//得到当前以及经写入的块的信息
		long currentOffset = rb.getOffset();
		int currentLength = rb.getLength();
		//再得到当前空闲块中的空块信息
		int index = getBlockIndex(currentOffset);
		long orgOffset = blockList.get(index).getOffset();
		long orgLength = blockList.get(index).getLength();
		//计算截断块的信息
		long leftOffset = orgOffset;
		long leftLength = (int) (orgOffset - currentOffset);
		long rightOffset = orgOffset + orgLength - currentOffset - currentLength;
		long rightLength = (int) (orgOffset + orgLength - currentOffset);
		
		blockList.remove(index);
		//TODO 疑问：如果进行了两次add操作，而index都是一样的，那么能不能在第一次插入之后，第二次插入追加到了第一次的后面呢？
		if(leftLength > 0) {
			blockList.add(new FileBlockInfo(leftOffset, leftLength));
		}
		if(rightLength > 0) {
			blockList.add(new FileBlockInfo(rightOffset, rightLength));
		}
	}
}
